package com.mrlv.ht.mapper;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import javax.persistence.Table;

import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.scripting.xmltags.SqlNode;
import org.apache.ibatis.scripting.xmltags.StaticTextSqlNode;

import com.github.abel533.mapperhelper.MapperHelper;
import com.github.abel533.mapperhelper.MapperTemplate;

public class SysMapperProvider extends MapperTemplate {

	public SysMapperProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
		super(mapperClass, mapperHelper);
	}
	/*
	 * 分析思路：
	 * 1.要获得MappedStatement对象
	 * 2.通过ms.getId()得到namespace.id，比如cn.tarena.ht.mapper.ModuleMapper.方法名
	 * 3.截串，截出namespace，这个namespace就是ModuleMapper接口的全路径
	 * 4.有了这个全路径名，就能够通过反射调用Calss.forName()得到这个接口类
	 * 5.这个类得到之后，就能够得到它的父接口类（泛型）
	 * 6.拿到这个父接口后，就能够获得这个接口泛型列的实体类，即Module
	 * 7.有了Module之后，就能够拿到类上的table注解，继而拿到name对应的表名
	 * 8.select count(*) from 表名
	 */
	public SqlNode selectCount(MappedStatement statement) {
		String namespaceId = statement.getId();//得到namespace.id，比如com.mrlv.ht.mapper.ModuLeMapper.countByExample
		
		String namespace = namespaceId.substring(0, namespaceId.lastIndexOf("."));//截串，截出接口的全路径名，比如cn.tarena.ht.mapper.ModuleMapper
		try {
			Class<?> interfaceClass = Class.forName(namespace);//根据接口的全路径名，生成对应的类(或接口)
			
			Type[] types = interfaceClass.getGenericInterfaces();//得到类(或接口)所实现的接口们，因为可以实现多个接口，所以是一个Type[]数组
			
			Type superInterface = types[0];//拿到Type[]数组里的第一个元素，这步相当于得到了SysMapper<T>
			ParameterizedType t = null;
			//判断是否是泛型类型
			if(superInterface instanceof ParameterizedType) {
				//把type类型的SystMapper<T>强转成泛型类型 ParameterizedType 的SysMapper<T>
				//为什么要强转？因为type就是一个干巴巴的接口，什么方法都没有。
				 t = (ParameterizedType)superInterface;
			}
			//这一步得到泛型接口里所有的实体类们
			Type[] entityClasses = t.getActualTypeArguments();
			//相当于得到Module这个类
			Class<?> entity=(Class<?>) entityClasses[0];
			//拿到类上的table注解，继而拿到表名
			String tableName=entity.getAnnotation(Table.class).name();
			String text="select count(*) from "+tableName;
			//把sql语句封装到SqlNode里返回
			SqlNode sqlNode = new StaticTextSqlNode(text);
			return sqlNode;
			
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
	
	public SqlNode findAll(MappedStatement ms) {
		//调用模板里的方法，直接得到泛型里的实体类
		Class<?> entityClass = this.getSelectReturnType(ms);
		//因为当前sql语句返回的结果集，是List<entityClass>类型，所以要指定返回值类型
		//但是如果返回值是int类型，则不用设置
		this.setResultType(ms, entityClass);
		//拿到类上的table注解，继而拿到表名
		String tableName = entityClass.getAnnotation(Table.class).name();
		String text = "select * from " + tableName;
		SqlNode sqlNode = new StaticTextSqlNode(text);
		return sqlNode;
	}

}
